/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin		 	*/
/*	Project:	GlbLib-1.0.0			*/
/*	Author:		gong_libin			*/
/*	Date:		2016_06_01			*/
/*	File:		GlbRaw.h			*/
/********************************************************/

#ifndef _GLBRAW_H
#define	_GLBRAW_H

#include "GlbNet.h"

#include <net/if.h>
#include <net/ethernet.h>
#include <sys/ioctl.h>
#include <netinet/ip.h>
#define	__FAVOR_BSD
#include <netinet/tcp.h>
#include <netinet/udp.h>

namespace GlbNet
{

#define	GLB_AF_INET			AF_INET
#define	GLB_PF_INET			PF_INET
#define	GLB_PF_PACKET			PF_PACKET

#define	GLB_SOCK_RAW			SOCK_RAW
#define	GLB_ETH_P_ALL			ETH_P_ALL

#define	GLB_IPPROTO_RAW			IPPROTO_RAW
#define	GLB_IPPROTO_TCP			IPPROTO_TCP
#define	GLB_IPPROTO_UDP			IPPROTO_UDP

class CGlbRaw : public CGlbNet
{
public:
	CGlbRaw();
	virtual ~CGlbRaw();

	void GlbRawReset();
	void* GlbRawGetAddr();
	void GlbRawSetAddr(void* pAddr);
	void GlbRawSetAddr(char* pszUrl);
	int GlbRawPromisc(char* pszDev, short sFlag);
	void GlbRawSetAddr(char* pszAddr, USHORT usPort);
	int GlbRawInitSend(int iDomain, int iType, int iProto);
	int GlbRawInitRecv(int iDomain, int iType, int iProto);
	void GlbRawTcpReset(UCHAR* puszHead, UCHAR* puszDst, int* piDst);
	void GlbRawTcpRedir(UCHAR* puszHead, char* pszSrc, int iSrc, UCHAR* puszDst, int* piDst);
	void GlbRawUdpRedir(UCHAR* puszHead, char* pszSrc, int iSrc, UCHAR* puszDst, int* piDst);

	virtual int GlbNetSend(UCHAR* puszPacket, int iLength);
	virtual int GlbNetRecv(UCHAR* puszPacket, int iLength);

protected:
	struct sockaddr_in m_stAddr;

private:
	USHORT GlbRawIPCheck(USHORT* pusIP, int iLength);
	USHORT GlbRawPortCheck(UCHAR ucPro, UCHAR* puszTcp, int iLength, struct in_addr stSrc, struct in_addr stDst);

	void GlbRawUdpHead(UCHAR* puszUdp, USHORT usSrc, USHORT usDst, int iLength);
	void GlbRawTcpHead(UCHAR* puszTcp, USHORT usSrc, USHORT usDst, ULONG ulSeq, ULONG ulAck);
	void GlbRawIPHead(UCHAR* puszIP, UCHAR ucPro, struct in_addr stSrc, struct in_addr stDst, USHORT usLength);

};

inline int CGlbRaw::GlbNetSend(UCHAR* puszPacket, int iLength)
{
	return sendto(CGlbNet::m_iSocket, puszPacket, iLength, 0, (struct sockaddr*)&m_stAddr, sizeof(struct sockaddr_in));
}

inline int CGlbRaw::GlbNetRecv(UCHAR* puszPacket, int iLength)
{
	return recvfrom(CGlbNet::m_iSocket, puszPacket, iLength, 0, NULL, NULL);
}

} /* GlbNet */

#endif /* _GLBRAW_H */
